
今天要來做的是滾動動畫,利用滑鼠滾輪來控制BOX從左右兩邊交叉的出現,倒回去也一樣可以XD! 那我們就直接開始吧
| 知識點 | 使用說明 | 
|---|---|
| flexbox | 佈局排版 | 
| box-shadow | 製作BOX的陰影效果 | 
| translateX( ) | 製作BOX的水平方向位移 | 
| transition | 控制BOX出現的動畫速度和效果 | 
| :nth-of-type() | 用來選擇"偶數號"的BOX | 
| 知識點 | 使用說明 | 
|---|---|
| window.innerHeight | 取得視窗內的網頁內容高度 | 
| Element.getBoundingClientRect() | 取得BOX距離視窗的位子 | 
| forEach() | 迭代每個BOX,並判斷BOX是否要顯示在畫面 | 
  <h1>Scroll to see the animation</h1>
    <div class="box"><h2>放入你想寫的標題</h2></div>
    <div class="box"><h2>放入你想寫的標題</h2></div>
    <div class="box"><h2>放入你想寫的標題</h2></div>
    <div class="box"><h2>放入你想寫的標題</h2></div>
    <!-- 後面都一樣,所以省略 -->
* {
  box-sizing: border-box;
}
body {
  background-color: #efedd6;
  margin: 0;
  padding: 0;
  display: flex; /*讓內容水平垂直置中*/
  flex-direction: column;
  justify-content: center;
  align-items: center;
  overflow-x: hidden;
}
在Day 3 progress steps進度條,我們有寫了一個CSS公版,這個公版在往後的賽project中可以作為一個初始模板,不過在這要稍微客製一下,加入flex-direction: column;讓排版轉為直向,不用設height,因為我們要透過滑鼠滾輪去製造效果,如果設定高度就沒意義了
主要內容
h1 {
  margin: 10px;
}
.box {
  background-color: rgb(158, 158, 242);
  color: white;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 250px;
  height: 150px;
  margin: 10px;
  border-radius: 10px;
  /* offset-x | offset-y | blur-radius | color */
  box-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3);
  transform: translateX(400%);  /*向右移動400%,若不寫預設為0*/
  transition: transform 0.4s ease;
}
.box:nth-of-type(even) {  /*even:偶數*/
  transform: translateX(-400%);
}
.box.show {
  transform: translateX(0);
}
↑ 這一段有幾個重點,第一個是使用了::nth-of-type(even)去找出偶數號的盒子
在最一開始的完成圖中,我們看到盒子是"左右交叉"的出現,但其實只要控制一邊的出現,就可以了做到這個效果了
第二個需要注意的就是,transform: translateX(位移距離)裡的位移距離,在預設情況下,BOX是在 transform: translateX(400%);的位子,因為我們設置overflow-x: hidden;,所以超過瀏覽器的範圍會被隱藏起來,不過要留意如果位移的單位是設%,它所參考的對象並非父元素,而是參考設置transform的那個元素
再來,我們為偶數號的BOX設了 transform: translateX(-400%);,所以所有偶數號的BOX們都會向左移動-400%,不過也因為設置了overflow-x: hidden;,所以也看不到它出現在畫面中
至於.box.show,眼尖的你可能會注意到我們在html中並沒有寫入這個class,疑?? 不過依照前幾篇的操作不是這樣阿! 這裡就是在為後面javaScript埋伏筆呀嘿嘿,因為我們要透過show這個類別去控制BOX的出現,它在預設情況下並沒有要"show",所以就不必寫在html中了
let boxes = document.querySelectorAll(".box");
window.addEventListener("scroll", checkBoxes);
checkBoxes();
function checkBoxes() {
  console.log(window.innerHeight);
  let triggerBottom = window.innerHeight * 0.8;
  boxes.forEach((box) => {
    let boxTop = box.getBoundingClientRect().top;
    if (boxTop < triggerBottom) {
      box.classList.add("show");
    } else {
      box.classList.remove("show");
    }
  });
}
JS可以拆成兩部分來講解,這時候真希望你有雙螢幕,看程式碼就不用一直滾動那麼辛苦XD
首先,要設置一個checkbox函式,我們要用它來檢查每個BOX的位子,那既然我們需要檢查每個BOX的位子,就必須想辦法知道每個BOX的觸發點(trigger point)在哪,以及當滑鼠滾輪向下,BOX進入畫面時,我們要做甚麼?(好繞口令XD)
那我針對有使用到的方法做簡單的介紹:
擷取MDN上的一段話
The Window interface represents a window containing a DOM document . Read-only innerHeight property of the Window interface returns the interior height of the window in pixels, including the height of the horizontal scroll bar, if present.
意思大致上是說,window是一個包含了DOM document的物件,其中innerHeight這個屬性,它是唯讀(Read-only)的,我們可以透過它取得視窗內的網頁內容高度,如果有水平卷軸也會包含進去。
 console.log(window.innerHeight);
從印出來的結果你會發現,當滾動滾輪時它會印出一個正整數,它是固定的數字(如下圖),不過我們為了要做出滑鼠滾輪的效果,它不能是固定的數字,因為在任何時候高度都有可能不同
let triggerBottom = window.innerHeight * 0.8;
triggerBottom代表觸發器的底部,值為 window.innerHeight 的 80%,你可以試試看不要乘任何數 or 乘更大 or 乘更小去測試看看,比較彼此的差別
一樣擷取MDN上的一段話
The Element.getBoundingClientRect() method returns a DOMRect object providing information about the size of an element and its position relative to the viewport.
意思大致上是說 getBoundingClientRect()可以用來知道一個元素的大小和位子,會回傳DOMRect,DOMRect其實就是一個矩形,它提供了這個矩形的大小和位子等相關資訊,可以看底下這張圖比較好理解,left, top, right, bottom, x, y...這些都是它提供的資訊,是可以取用的屬性

本圖擷取自MDN
box.getBoundingClientRect().top; 是我們想知道BOX距離視窗的高度在哪,它有沒有小於triggerBottom 這個變數,如果小於的話,我們要新增(add()) "show"這個類別,否則就移除(remove())
那今天的解說都到這邊,關於計算視窗的高度會比較難理解,自己也是透過實作的過程一邊去消化吸收,不懂的就console.log()印出來看看到底那是甚麼東西,如果有任何問題可以底下留言,我會盡我所能回答你XD
附上codepen連結 https://codepen.io/hangineer/pen/qBYNyYY?editors=1100
所學不精,若有解說不夠詳盡或是錯誤歡迎指教,感激不盡!那明天見囉
[補充]
50 Projects In 50 Days - HTML, CSS & JavaScript
網頁座標 - 了解 screen、page、client 差異